<?php

/**
 * Базовый класс формы восстановления забытого пароля — для пользователя и для
 * админа.
 *
 */
abstract class Security_Action_Forgot extends Kernel_Action_Form 
{

    /**
     * Роль, которой должен принадлежать пользователь, чтобы восстановить пароль
     * через данную форму.
     *
     * @var integer
     */
    protected $_role;

    /**
     * Путь к файлу шаблона страницы с сообщением о том, что форма сохранена.
     * Если не указан, форма просто будет перерисована.
     *
     * @var string
     */
    protected $_template_saved = 'user/forgot/confirmation-sent.tpl';

    /**
     * Флаг, указывающий, что после сохранения данных формы не нужно показывать
     * сответствующее сообщение.
     *
     * @var boolean
     */
    protected $_no_message = true;

    /**
     * Костыль это.
     *
     * @var boolean
     */
    private $_saved = false;

    /**
     * Инициализирует элементы формы.
     *
     */
    protected function _initElements() 
    {
        $this->_addElement('email', 'string', array(
            'required' => true,
            'validators' => array(
                array('Security_Validator_Forgot', array('role' => $this->_role))
            ),
            'value' => Application::getRequest()->get('email'),
        ));
    }

    /**
     * Сохраняет данные формы. Генерирует хэш и отправляет пользователю почтовое
     * сообщение.
     *
     */
    protected function _save()
    {
        $email = $this->_getValue('email');
        
        // определяем из конфигурации системы, используются ли секретные вопросы,
        // и определены ли они для этого пользователя - чтоб не было проблем при
        // изменении конфигурации в ходе работы проекта, потом подробнее опишу
        
        if ($this->_hasQuestions($email)) 
        {
            // :KLUDGE: morozov 17092007: вгрязную снимаем шаблон сохраненной страницы
            // :KLUDGE: dV 23072008: а вообще-то нужно бы присмотреться к Kernel_Form_Wizard,
            // т.к. это получается сложная форма
            $this->_template_saved = null;
            $this->_self_redirect = false;
            $this->_forward(new Security_Action_Forgot_Step2);
            
        } 
        else 
        {
            // генерируем хэш для аккаунта с указанным email
            $hash = Confirm::create(Security_Utils_Subject::getSubjectByEmail($email), 'security', 'reset');

            // определяем идентификатор профайла, данные из которого нужно
            // подставить в почтовое сообщение
            $profile = $this->_getProfileId($email);

            // отправляем пользователю письмо
            $this->_send($profile, $hash);
        }
        
        $this->_saved = true;
    }
    
    /**
     * Выводит данные формы в шаблон.
     *
     */
    protected function _draw()
    {
        // :KLUDGE: dV 23072008: костыли свистят над головами (см. выше)
        if (!$this->_saved) parent::_draw();
    }

    /**
     * Отправляет сообщение указанному пользователю.
     *
     * @param   integer $profile
     * @param   string  $hash
     * @return  boolean
     */
    abstract protected function _send($profile, $hash);

    /**
     * Возвращает секретные указанного субъекта безопасности.
     *
     * @param   integer  $subject
     * @return  array
     */
    private function _getQuestions($subject)
    {
        return Security_Utils_Subject::getQuestions($subject);
    }

    /**
     * Возвращает идентификатор профайла с указанным email.
     *
     * @param   string  $email
     * @return  integer
     */
    private function _getProfileId($email)
    {
        return Security_Utils_Subject::getProfileId($email, $this->_role);
    }

    /**
     * Определяет, указаны ли секретные вопросы для аккаунта с указанным e-mail.
     *
     * @param   string  $email
     * @return  boolean
     */
    private function _hasQuestions($email)
    {
        return Kernel_Config::get('security', 'questions') > 0
            && Security_Utils_Subject::hasQuestions($email);
    }
    
}
